package day_05_03_FourFunctionalInterface;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * @Description
 * @Author shihan
 * @Date 2020/11/8 15:14
 * @Version 1.0
 */
public class StreamDemo {

    /**
     * @param args
     *【题目】：按照给出数据，找出同时满足以下条件的用户，也即下面条件全部满足
     *          偶数ID 且 年龄大于24 且 用户名转为大写 且 用户名字母倒排序 
     *          只输出一个用户名
     */
    public static void main(String[] args) {
        User u1 = new User(11, "a", 23);
        User u2 = new User(12, "b", 24);
        User u3 = new User(13, "c", 22);
        User u4 = new User(14, "d", 28);
        User u5 = new User(16, "e", 26);

        List<User> list = Arrays.asList(u1,u2,u3,u4,u5);

        //oldWay(list);

        //fourFunctionalInterface();

        streamWay(list);

    }

    private static void streamWay(List<User> list) {
        list.stream()
                .filter(t -> {return t.getId() % 2 == 0;})
                .filter(t -> {return t.getAge() > 24;})
                .map(t -> {return t.getUserName().toUpperCase();})
                .sorted((o1,o2) -> {return -o1.compareTo(o2);})
                .limit(1)
                .forEach(System.out::println);
    }

    //jdk自带的四大函数式接口
    private static void fourFunctionalInterface() {
        /*
        Function<String,Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        };
        */
        //【知识点回顾】：lambda表达式，可以代替函数式接口的匿名实现类；
        //【知识点一】：Function<T,R> 函数接口，接收一个参数，并返回一个结果
        Function<String,Integer> function = (s) -> { return s.length(); };
        System.out.println(function.apply("hello world!"));

        //【知识点二】：Predicate<T> 判定接口，接收一个参数，并返回一个 true false 类型的结果
        Predicate<String> predicate = (s) -> { return s.isEmpty(); };
        System.out.println(predicate.test(""));

        //【知识点三】：Consumer<T> 消费接口，接收一个参数，并且没有返回值类型--void
        Consumer<String> consumer = (s) -> { System.out.println(s); };
        consumer.accept("Hello World!");

        //【知识点四】：Supplier<T> 供给接口，不接收参数，但是返回一个结果
        Supplier<String> supplier = () -> { return "abc"; };
        System.out.println(supplier.get());

    }

    //不采用流式计算的古老方式实现
    private static void oldWay(List<User> list) {
        List<String> res = new ArrayList<>(5);
        for (User user : list) {
            if(user.getId()%2==0 && user.getAge()>24){
                res.add(user.getUserName().toUpperCase());
            }
        }
        res.sort((str1,str2) -> {
            return -str1.compareTo(str2);
        });
        for (String s : res) {
            System.out.println(s);
        }
    }

}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
class User{
    private Integer id;
    private String userName;
    private int age;
}
